package com.naiterui.ehp.bp.utils.date;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.TemporalUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
 * 功能概述：<br>
 * 时间处理工具类
 *
 * @author guoyongxiang
 */
public class DateUtil {

    /**
     * The Constant YEAR.
     */
    public static final String YEAR = "year";
    /**
     * The Constant MONTH.
     */
    public static final String MONTH = "month";
    /**
     * The Constant DAY.
     */
    public static final String DAY = "day";
    /**
     * The Constant WEEK.
     */
    public static final String WEEK = "week";
    /**
     * The Constant HOUR.
     */
    public static final String HOUR = "hour";
    /**
     * The Constant MINUTE.
     */
    public static final String MINUTE = "minute";
    /**
     * The Constant SECOND.
     */
    public static final String SECOND = "second";
    /**
     * 中文-年
     */
    public static final String YEAR_CN = "年";
    /**
     * 中文-月
     */
    public static final String MONTH_CN = "月";
    /**
     * 中文-日
     */
    public static final String DAY_CN = "日";
    /**
     * 毫秒-秒换算单位：<code>SECOND_TIME</code>
     */
    public static final int MILLISECOND_UNIT = 1000;
    /**
     * The Constant YEAR_MONTH_FORMAT.<br>
     * yyyy-MM
     */
    public static final String YEAR_MONTH_FORMAT = "yyyy-MM";
    /**
     * The Constant YEAR_MONTH_FORMAT_CN.<br>
     * yyyy年MM月
     */
    public static final String YEAR_MONTH_FORMAT_CN = "yyyy年MM月";
    /**
     * The Constant DATE_TIME_FORMAT.<br>
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * The Constant DATE_TIME_FORMAT.<br>
     * yyyy-MM-dd HH:mm
     */
    public static final String DATE_TIME = "yyyy-MM-dd HH:mm";
    /**
     * The Constant DAY_TIME_FORMAT.<br>
     * yyyyMMdd
     */
    public static final String DAY_TIME_FORMAT = "yyyyMMdd";
    /**
     * The Constant DATE_TIME_FORMAT_MIN.<br>
     * yyyyMMddHHmmss
     */
    public static final String DATE_TIME_FORMAT_MIN = "yyyyMMddHHmmss";
    /**
     * The Constant DATE_FORMAT.<br>
     * yyyy-MM-dd
     */
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    /**
     * The Constant DATE_FORMAT.BY "/"<br>
     * yyyy/MM/dd
     */
    public static final String DATE_FORMAT_BY_DIAGONAL = "yyyy/MM/dd";
    /**
     * The Constant DATE_FORMAT.BY "/"<br>
     * yyyy/MM/dd HH:mm
     */
    public static final String DATE_FORMAT_BY_DIAGONAL_MIN = "yyyy/MM/dd HH:mm";
    /**
     * The Constant DATE_FORMAT.<br>
     * yyyy年MM月dd日
     */
    public static final String DATE_FORMAT_CN = "yyyy年MM月dd日";
    /**
     * The Constant DATE_FORMAT.<br>
     * dd
     */
    public static final String DATE_FORMAT_DAY = "dd";
    /**
     * The Constant DATE_WEEK_FORMAT.<br>
     * MM-dd EEEE
     */
    public static final String DATE_WEEK_FORMAT = "MM-dd EEEE";
    /**
     * The Constant TIME_MIN_FORMAT.<br>
     * HH:mm
     */
    public static final String TIME_MIN_FORMAT = "HH:mm";
    /**
     * The Constant MONTH_DAY_FORMAT.<br>
     * MM-dd
     */
    public static final String MONTH_DAY_FORMAT = "MM-dd";
    /**
     * 时间格式转换 Cron表达式：<code>CRON_TIME_FORMAT</code>
     */
    public static final String CRON_TIME_FORMAT = "ss mm HH dd MM ? yyyy";
    public static final String MONTH_DAY_HH_DD_FORMAT = "MM月dd日  HH:mm";
    /**
     * The Constant DATE_FORMAT.<br>
     * MM-dd HH:mm:ss
     */
    public static final String MONTH_DAY_HOUR_MINUTE_SECOND_FORMAT = "MM-dd HH:mm:ss";
    /**
     * The Constant DATE_TIME_FORMAT_IN_COMMA_DATE.<br>
     * yyyy.MM.dd HH:mm:ss
     */
    public static final String DATE_TIME_FORMAT_IN_COMMA_DATE = "yyyy.MM.dd HH:mm:ss";
    /**
     * The Constant DATE_FORMAT_IN_COMMA_DATE.<br>
     * yyyy.MM.dd
     */
    public static final String DATE_FORMAT_IN_COMMA_DATE = "yyyy.MM.dd";

    public static final String MAX_TIME_IN_DAY = "23:59:59";
    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);

    /**
     * 判断参数是否等于null或者空
     *
     * @param param
     *
     * @return
     */
    public static boolean checkParam(Object param) {
        return null == param || "".equals(param);
    }

    /**
     * 得到当前系统时间:毫秒数
     *
     * @return
     */
    public static long getCurrentTimeMillis() {
        return System.currentTimeMillis();
    }

    /**
     * 得到当前系统时间:无任何格式化
     *
     * @return 格林威治时间
     */
    public static Date getCurrentDate() {
        return new Date(getCurrentTimeMillis());
    }

    /**
     * 得到当前系统时间并转化为字符串：系统默认显示格式
     *
     * @return 系统默认时间显示格式 19位字符串
     */
    public static String getCurrentFormatDateTime() {
        Date date = getCurrentDate();
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return dateFormat.format(date);
    }

    /**
     * 得到当前系统日期并转化为字符串：系统默认显示格式
     *
     * @return 系统默认日期显示格式 10位字符串
     */
    public static String getCurrentFormatDate() {
        Date date = new Date(getCurrentTimeMillis());
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT);
        return dateFormat.format(date);
    }

    /**
     * 得到当前系统时间并转化为字符串：指定显示格式
     *
     * @param pattern e.g.DATE_FORMAT_8 = "yyyyMMdd"; DATE_TIME_FORMAT_14 =
     *                "yyyyMMddHHmmss"; 或者类似于二者的格式 <br>
     *                e.g."yyyyMMddHH"，"yyyyMM"
     *
     * @return
     */
    public static String getCurrentCustomizeFormatDate(String pattern) {
        if (checkParam(pattern)) {
            return "";
        }
        Date date = getCurrentDate();
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.format(date);
    }

    /**
     * 输入日期，按照指定格式返回
     *
     * @param date
     * @param pattern e.g.DATE_FORMAT_8 = "yyyyMMdd"; DATE_TIME_FORMAT_14 =
     *                "yyyyMMddHHmmss"; 或者类似于二者的格式 <br>
     *                e.g."yyyyMMddHH"，"yyyyMM"
     *
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        if (checkParam(pattern) || checkParam(date)) {
            return "";
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);

        return dateFormat.format(date);
    }

    /**
     * 输入日期，按照指定格式和地区标识符返回
     *
     * @param date
     * @param pattern e.g.DATE_FORMAT_8 = "yyyyMMdd"; DATE_TIME_FORMAT_14 =
     *                "yyyyMMddHHmmss"; 或者类似于二者的格式 <br>
     *                e.g."yyyyMMddHH"，"yyyyMM"
     * @param locale  国家地区， e.g.new Locale("zh","CN","") 中国 Locale.getDefault();
     *
     * @return
     */
    public static String formatDate(Date date, String pattern, Locale locale) {
        if (checkParam(pattern) || checkParam(date)) {
            return "";
        }
        if (checkParam(locale)) {
            locale = Locale.getDefault();
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, locale);
        return dateFormat.format(date);
    }

    /**
     * 将时间字符串按照默认格式DATE_FORMAT = "yyyy-MM-dd"，转换为Date
     *
     * @param dateStr
     *
     * @return
     */
    public static Date parseStrToDate(String dateStr) {
        if (checkParam(dateStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT);
        return dateFormat.parse(dateStr, new ParsePosition(0));
    }

    /**
     * 将时间字符串按照默认格式DATE_TIME_FORMAT ="yyyy-MM-dd HH:mm:ss",转换为Date
     *
     * @param dateStr
     *
     * @return
     */
    public static Date parseStrToDateTime(String dateStr) {
        if (checkParam(dateStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return dateFormat.parse(dateStr, new ParsePosition(0));
    }

    /**
     * 将时间或者时间日期字符串按照指定格式转换为Date
     *
     * @param dateStr
     * @param pattern
     *
     * @return
     */
    public static Date parseStrToCustomPatternDate(String dateStr, String pattern) {
        if (checkParam(pattern) || checkParam(dateStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Date date = dateFormat.parse(dateStr, new ParsePosition(0));
        return date;
    }

    /**
     * 日期天数增加
     *
     * @param date
     * @param days
     *
     * @return
     */
    public static Date addDays(Date date, int days) {
        if (checkParam(date)) {
            return null;
        }
        if (0 == days) {
            return date;
        }
        Locale locale = Locale.getDefault();
        Calendar calendar = new GregorianCalendar(locale);
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    public static Date addMonth(Date date, int months) {
        if (checkParam(date)) {
            return null;
        }
        if (0 == months) {
            return date;
        }
        Locale locale = Locale.getDefault();
        Calendar calendar = new GregorianCalendar(locale);
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, months);
        return calendar.getTime();
    }

    /**
     * 日期天数减少
     *
     * @param date
     * @param days
     *
     * @return
     */
    public static Date minusDays(Date date, int days) {
        return addDays(date, 0 - days);
    }

    /**
     * 日期小时增加
     *
     * @param date
     * @param hours
     *
     * @return
     */
    public static Date addHours(Date date, int hours) {
        if (checkParam(date)) {
            return null;
        }
        if (0 == hours) {
            return date;
        }
        Locale locale = Locale.getDefault();
        Calendar calendar = new GregorianCalendar(locale);
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, hours);
        return calendar.getTime();
    }

    /**
     * 日期分钟增加
     *
     * @param date
     * @param minute
     *
     * @return
     */
    public static Date addMinutes(Date date, int minute) {
        if (checkParam(date)) {
            return null;
        }
        if (0 == minute) {
            return date;
        }
        Locale locale = Locale.getDefault();
        Calendar calendar = new GregorianCalendar(locale);
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }

    /**
     * 日期分钟减少
     * DateUtil.minusMinutes()
     *
     * @param date
     * @param minute
     *
     * @return
     *
     * @Author fanjd
     * @Date 2017年6月19日
     * @since 1.0.0
     */
    public static Date minusMinutes(Date date, int minute) {
        return addMinutes(date, -minute);
    }

    /**
     * 日期秒增加
     *
     * @param date
     * @param seconds
     *
     * @return
     */
    public static Date addSeconds(Date date, int seconds) {
        if (checkParam(date)) {
            return null;
        }
        if (0 == seconds) {
            return date;
        }
        Locale locale = Locale.getDefault();
        Calendar calendar = new GregorianCalendar(locale);
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    /**
     * 日期大小比较
     *
     * @param dateOne
     * @param dateOther
     *
     * @return int
     * Created on Aug 15, 2007 12:41:30 AM
     */
    public static long compareDate(Date dateOne, Date dateOther) {
        return dateOne.getTime() - dateOther.getTime();
    }


    /**
     * 获得两个指定的天数差 单位为天
     *
     * @param startTime
     * @param endTime
     *
     * @return
     */
    public static int getTotalDay(Date startDay, Date endDay) {
        if (checkParam(startDay) || checkParam(endDay)) {
            return 0;
        }
        Locale locale = Locale.getDefault();
        Calendar start = new GregorianCalendar(locale);
        Calendar end = new GregorianCalendar(locale);
        start.setTime(startDay);
        end.setTime(endDay);
        int y = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
        if (y != 0) {
            return end.get(Calendar.DAY_OF_YEAR) - start.get(Calendar.DAY_OF_YEAR) + 365 * y;
        } else {
            return end.get(Calendar.DAY_OF_YEAR) - start.get(Calendar.DAY_OF_YEAR);
        }
    }

    /**
     * 根据当前日期获取0点的时间
     *
     * @param date
     *
     * @return Date
     * Created on Mar 29, 2007 11:10:43 AM
     */
    public static Date convertDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 00);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 根据当前日期获取整点的时间
     *
     * @param date
     *
     * @return Date
     */
    public static Date convertHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 把日期格式化成字符串
     *
     * @param date
     * @param fromat
     *
     * @return
     */
    public static String parseDateToString(Date date, String fromat) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(fromat);
        return dateFormat.format(date);
    }

    /**
     * 根据小时字符串获取小时所在日期
     *
     * @param hourStr
     *
     * @return
     */
    public static Date getHourDate(String hourStr) {
        if (checkParam(hourStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_MIN_FORMAT);
        Date date = dateFormat.parse(hourStr, new ParsePosition(0));

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static int getWeekNum(Date date) {
        int weekDay = 0;
        if (date != null) {
            Calendar c = Calendar.getInstance();
            try {
                c.setTime(date);
                int d = c.get(Calendar.DATE);
                c.set(Calendar.DATE, d - 1);
                weekDay = c.get(Calendar.DAY_OF_WEEK);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        return weekDay;
    }


    /**
     * 判断某两个字符串表示的 日期/时间 的前后关系
     *
     * @param dateStr1
     * @param dateStr2
     * @param formatStr 字符串格式
     *
     * @return 前面的字符串代表的时间比较前、返回true
     */
    public static boolean checkDayBeforeDayByStr(String dateStr1, String dateStr2, String formatStr) {
        try {
            if (StringUtils.isNotBlank(dateStr1) || StringUtils.isNotBlank(dateStr2)) {
                Date d1 = DateUtil.parseStrToCustomPatternDate(dateStr1, formatStr);
                Date d2 = DateUtil.parseStrToCustomPatternDate(dateStr2, formatStr);
                if (d1.before(d2)) {
                    return true;
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return false;
    }

    /**
     * <获取目前距离当天结算剩余的秒数>
     *
     * @return int <返回值描述>
     *
     * @Throws 异常信息
     * @History 2015年7月7日 下午7:14:35 by chenlin
     */
    public static int getDayOfSecond() {
        long now = System.currentTimeMillis();
        String date = parseDateToString(new Date(now), DATE_FORMAT);
        Date nowDate = parseStrToCustomPatternDate(date + " 23:59:59", DATE_TIME_FORMAT);
        long maxDay = nowDate.getTime();
        return (int) (maxDay - now) / 1000;
    }

    /**
     * 校验某一时间是否在某一时间段范围内
     * DateUtil.rangeCompare()
     *
     * @param checkTime      校验时间
     * @param rangeStartTime 范围开始时间
     * @param rangeEndTime   范围结束时间
     *
     * @return
     *
     * @Author fangguanhong
     * @Date 2016-2-1
     * @since 1.0.0
     */
    public static boolean rangeCompare(Date checkTime, Date rangeStartTime, Date rangeEndTime) {
        int checkStart = checkTime.compareTo(rangeStartTime);
        int checkEnd = rangeEndTime.compareTo(checkTime);
        return checkStart > 0 && checkEnd > 0;
    }

    /**
     * 返回指定日期的0点日历
     * DateUtil.getStartTime()
     *
     * @param c 为空时返回当天0点
     *
     * @return
     *
     * @Author Amber
     * @Date 2016年8月6日
     * @since 1.0.0
     */
    public static Calendar getStartTime(Calendar c) {
        if (c == null) {
            c = Calendar.getInstance();
        }
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c;
    }

    /**
     * 增加时间
     *
     * @param date
     * @param amountToAdd
     * @param unit        java.time.temporal.ChronoUnit
     *
     * @return
     */
    public static Date plus(Date date, long amountToAdd, TemporalUnit unit) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.of("Asia/Shanghai");
        LocalDateTime newDate = LocalDateTime.ofInstant(instant, zone).plus(amountToAdd, unit);
        return Date.from(newDate.atZone(zone).toInstant());
    }

    /**
     * 将字符串类型日期转为unix时间戳
     * @param dateStr 日期字符串
     * @return unix时间戳
     */
    public static Long dateStr2Unix(String dateStr){
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return dateFormat.parse(dateStr, new ParsePosition(0)).getTime() / 1000;
    }

    public static void main(String[] args) {
        System.out.println(DateUtil.formatDate(DateUtil.getStartTime(null).getTime(), DateUtil.DATE_TIME_FORMAT));
    }
}
